package cn.kgc.security;


import cn.kgc.service.UsersService;
import cn.kgc.service.impl.MenusServiceImpl;
import cn.kgc.util.JwtUtil;
import cn.kgc.util.cache.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

@Component
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Resource
    private UserDetailsService userDetailsService;
    @Resource
    private UsersService usersService;
    @Resource
    private JwtUtil jwtUtil;
    @Resource
    private RedisUtil redisUtil;
    @Autowired
    private MenusServiceImpl menusService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
    }

    /**
     * security忽略的请求
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/favicon.ico", "/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**", "/doc.html");
    }

    /**
     * 配置需要验证的接口以及接口使用哪些过滤器进行验证
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                // 指定某些接口不需要通过验证即可访问。登陆接口肯定是不需要认证的
                .antMatchers("/users/login").permitAll()
                // 这里意思是其它所有接口需要认证才能访问
                .anyRequest().authenticated()

                .and()
                .csrf().disable()  //关闭csrf跨站请求伪造
                .cors()    //开启跨域以便前端调用接口

                .and()
                .addFilterBefore(
                        new TokenAuthenticationFilter(jwtUtil, redisUtil, usersService, menusService),
                        UsernamePasswordAuthenticationFilter.class
                ).addFilter(
                        new AuthenticationFilter(authenticationManager(), jwtUtil)
                ).sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);  //禁用session
    }
}
